/*
 * @Description: Calculator 计算器
 * 
 * @Author: rendc
 * 
 * @Date: 2025-06-27 10:16:50
 * 
 * @LastEditors: 张旭东 zxd12345688@qq.com
 * 
 * @LastEditTime: 2025-06-29 09:28:45
 */
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.script.ScriptException;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.SwingUtilities;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.math.BigDecimal;
import java.math.RoundingMode;

public class Calculator extends JFrame implements ActionListener {
  private JPanel north, center;
  private JTextField field;
  private JButton[] btns;
  private boolean newCalculation = false; 

  public Calculator() {
    setTitle("计算器");
    setSize(700, 700);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    initComponent();
    setVisible(true);
  }
  private void initComponent() {
    
    north = new JPanel();
    center = new JPanel();
    field = new JTextField();
    field.setPreferredSize(new Dimension(700,150));
    field.setEditable(false);
    field.setFont(new Font("SansSerif",Font.BOLD,35));
    String[] str=new String[]{
      "7","8","9","+",
      "4","5","6","-",
      "1","2","3","×",
      "0",".","=","÷",
      "C","B","T","S"
    };
    btns=new JButton[str.length];
    for(int i=0;i<btns.length;i++){
      btns[i]=new JButton(str[i]);
      btns[i].setFont(new Font("SansSerif",Font.BOLD,25));
    }
    
    north.setLayout(new BorderLayout());
    center.setLayout(new GridLayout(5,4));
    north.add(field, BorderLayout.CENTER);
    for(JButton btn:btns){
      center.add(btn);
    }
    add(north, BorderLayout.NORTH);
    add(center);
    for(JButton btn:btns){
      btn.addActionListener(this);
    }
  }
  private void setBtnText(String text){
    switch (text){
      case "C":
        field.setText("");
        newCalculation=false;
        break;
      case "B":
        if(!newCalculation && field.getText().length()!=0){
          String numText=field.getText();
          field.setText(numText.substring(0,numText.length()-1));
        }
        break;
      case "T":
        java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentDateTime = dateFormat.format(new java.util.Date());
        field.setText(currentDateTime);
        newCalculation = true;
        break;
      case "S":
        String gen = field.getText();
        try {
          if (gen.isEmpty() || isOperator(gen.charAt(gen.length() - 1))) {
            field.setText("0");
          }
          double value = Double.parseDouble(field.getText());
          if (value < 0) {
            field.setText("无效输入");
          } else {
            double result = Math.sqrt(value);
            field.setText(String.valueOf(result));
          }
          newCalculation = true;
        } catch (NumberFormatException e) {
          field.setText("格式错误");
        }
        break;
      case "=":
        calculate();
        newCalculation = true;
        break;
      case ".":
        String currentText = field.getText();
        if(newCalculation){
          field.setText("0.");
          newCalculation = false;
        } 
        else if(currentText.isEmpty()){
          field.setText("0.");
        } 
        else if(isOperator(currentText.charAt(currentText.length()-1))){
          field.setText(currentText + "0.");
        } 
        else {
          int lastOpIndex = -1;
          for(int i = currentText.length()-1; i >= 0; i--){
            if(isOperator(currentText.charAt(i))){
              lastOpIndex = i;
              break;
            }
          }
          String lastNumber = lastOpIndex == -1 ? 
            currentText : 
            currentText.substring(lastOpIndex+1);
          if(!lastNumber.contains(".")){
            field.setText(currentText + ".");
          }
        }
        break;      
      default:
        String zz=field.getText();
        if(newCalculation && (Character.isDigit(text.charAt(0)) || text.equals("."))){
          field.setText(text);
          newCalculation = false;
        } 
        else if (!zz.isEmpty() && isOperator(zz.charAt(zz.length()-1)) && isOperator(text.charAt(0))){    
          field.setText(zz.substring(0, zz.length()-1) + text);
        }
        else{
          field.setText(zz+text);
        }
        break;
    }
  }
  private boolean isOperator(char c){
    return c == '+' || c == '-' || c == '×' || c == '÷';
  }
  
  private void calculate(){
    String expression=field.getText();
    System.out.println("计算表达式: " + expression); // 调试输出
    expression = expression.replace("×", "*");
    expression = expression.replace("÷", "/");
    
    // 处理小数精度问题
    try {
      // 使用BigDecimal进行精确计算
      String[] parts = splitExpression(expression);
      if (parts != null) {
        System.out.println("解析结果: " + parts[0] + " " + parts[1] + " " + parts[2]); // 调试输出
      }
      
      if (parts == null || parts.length != 3) {
        // 如果无法拆分为三个部分，尝试使用JavaScript引擎计算
        // 规范化表达式，确保以0开头的多位数字被正确处理
        String normalizedExpr = normalizeExpression(expression);
        System.out.println("规范化后的表达式: " + normalizedExpr);
        
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        Object result = engine.eval(normalizedExpr);
        field.setText(formatResult(result.toString()));
        return;
      }
      
      BigDecimal num1 = new BigDecimal(parts[0]);
      BigDecimal num2 = new BigDecimal(parts[2]);
      BigDecimal result;
      
      switch (parts[1]) {
        case "+":
          result = num1.add(num2);
          break;
        case "-":
          result = num1.subtract(num2);
          break;
        case "*":
          result = num1.multiply(num2);
          break;
        case "/":
          if (num2.compareTo(BigDecimal.ZERO) == 0) {
            field.setText("错误：除以零");
            return;
          }
          // 除法需要指定精度和舍入模式
          result = num1.divide(num2, 10, RoundingMode.HALF_UP);
          break;
        default:
          field.setText("不支持的运算符");
          return;
      }
      
      // 格式化结果，移除末尾的零
      field.setText(formatResult(result.toPlainString()));
    } catch (Exception e) {
      System.out.println("计算错误: " + e.getMessage()); // 调试输出
      // 如果手动计算失败，尝试使用JavaScript引擎
      try {
        // 规范化表达式，确保以0开头的多位数字被正确处理
        String normalizedExpr = normalizeExpression(expression);
        System.out.println("规范化后的表达式: " + normalizedExpr);
        
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        Object result = engine.eval(normalizedExpr);
        field.setText(formatResult(result.toString()));
      } catch (ScriptException ex) {
        field.setText("运算错误");
        ex.printStackTrace();
      }
    }
  }
  
  // 分割表达式为操作数和运算符
  private String[] splitExpression(String expression) {
    // 处理空表达式
    if (expression == null || expression.trim().isEmpty()) {
      return null;
    }
    
    // 去除前后空格
    expression = expression.trim();
    
    // 查找最后一个运算符位置
    int opIndex = -1;
    char opChar = ' ';
    
    // 按优先级查找运算符: 先查找×/，再查找+-
    String operators = "*+/+-";
    for (int i = operators.length() - 1; i >= 0; i--) {
      char op = operators.charAt(i);
      int index = expression.lastIndexOf(op);
      if (index > 0 && isOperatorValid(expression, index)) {
        opIndex = index;
        opChar = op;
        break;
      }
    }
    // 如果找到有效运算符
    if (opIndex > 0) {
      String num1 = expression.substring(0, opIndex).trim();
      String num2 = expression.substring(opIndex + 1).trim();
      // 检查操作数是否有效
      if (!num1.isEmpty() && !num2.isEmpty()) {
        return new String[]{num1, String.valueOf(opChar), num2};
      }
    }
    return null;
  }
  // 检查运算符位置是否有效
  private boolean isOperatorValid(String expr, int index) {
    // 确保运算符前后都有数字或小数点
    if (index == 0) return false; // 不能是第一个字符
    // 检查前面是否是数字或小数点
    char prevChar = expr.charAt(index - 1);
    if (!(Character.isDigit(prevChar) || prevChar == '.')) {
      return false;
    }
    // 检查后面是否是数字或小数点
    if (index >= expr.length() - 1) return false;
    char nextChar = expr.charAt(index + 1);
    if (!(Character.isDigit(nextChar) || nextChar == '.')) {
      return false;
    }

    return true;
  }
  
  // 规范化表达式，确保以0开头的多位数字被正确处理
  private String normalizeExpression(String expr) {
    // 正则表达式匹配以0开头的多位数字（排除0本身和小数）
    String regex = "\\b0+(\\d+)\\b";
    return expr.replaceAll(regex, "parseInt('$1', 10)");
  }
  // 格式化结果，移除末尾的零
  private String formatResult(String result) {
    if (result.contains(".")) {
      String[] parts = result.split("\\.");
      String decimal = parts[1];
      // 移除末尾的零
      decimal = decimal.replaceAll("0+$", "");
      if (decimal.isEmpty()) {
        return parts[0];
      } else {
        return parts[0] + "." + decimal;
      }
    }
    return result;
  }
  @Override
  public void actionPerformed(ActionEvent a) {
    Object source=a.getSource();
    if(source instanceof JButton){
      JButton btn=(JButton)source;
      String text=btn.getText();
      setBtnText(text);
    }
  }
  public static void main(String[] args) {
    SwingUtilities.invokeLater(Calculator::new);
  }
}